package com.qf.smartdevice.service.impl;

import com.github.pagehelper.PageInfo;
import com.qf.smartdevice.cache.CategoryCache;
import com.qf.smartdevice.events.CategoryCacheChangeEvent;
import com.qf.smartdevice.events.enums.CheckType;
import com.qf.smartdevice.exception.AddDataException;
import com.qf.smartdevice.exception.ErrorCode;
import com.qf.smartdevice.exception.QueryDataException;
import com.qf.smartdevice.exception.UpdateDataException;
import com.qf.smartdevice.mapper.SysCategoryMapper;
import com.qf.smartdevice.pojo.SysCategory;
import com.qf.smartdevice.pojo.SysUserInfo;
import com.qf.smartdevice.service.SysCategoryService;
import com.qf.smartdevice.utils.LoginUserInfoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 王博康
 * @version 1.0
 * @project devicemanagementsystem
 * @description: TODO
 * @date 2022/3/20 11:45 星期日
 */
@Service
@Transactional
public class SysCategoryServiceImpl implements SysCategoryService {

    private ApplicationContext applicationContext;
    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    private SysCategoryMapper sysCategoryMapper;
    @Autowired
    public void setSysCategoryMapper(SysCategoryMapper sysCategoryMapper) {
        this.sysCategoryMapper = sysCategoryMapper;
    }

    private CategoryCache categoryCache;
    @Autowired
    public void setCategoryCache(CategoryCache categoryCache) {
        this.categoryCache = categoryCache;
    }

    @Override
    public void addCategory(SysCategory sysCategory) {
        //判空
        Assert.isTrue(!sysCategory.isEmpty(CheckType.ADD),()->{
            throw new AddDataException("分类名称不能为空",ErrorCode.DATA_NULL);
        } );
        //判断是否登录
        //因为之前约定登录后在session中放入userInfo,故能否拿到该信息作为已登录的条件
        //拿取信息的过程可包装成工具类
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        SysUserInfo userInfo = (SysUserInfo)request.getSession().getAttribute("user");
        //拿到后断言判断
        Assert.notNull(userInfo,()->{
            throw new AddDataException("未登录",ErrorCode.NOT_LOGIN );
        } );
        //补充数据
        sysCategory.setCreateBy(userInfo.getUsername());
        sysCategory.setCreateTime(new Date());
        //添加到数据库
        sysCategoryMapper.addCategory(sysCategory);
        //数据变化需发布通知,通知缓存更新
        applicationContext.publishEvent(new CategoryCacheChangeEvent());
    }

    @Override
    public PageInfo<SysCategory> findByPage(int pageNum, int pageSize, String categoryName) {
        //开启分页
        //todo：测试缓存中拿数据时，开启分页的作用
//        PageHelper.startPage(pageNum,pageSize );
        List<SysCategory> categoryList = categoryCache.getSysCategoryList();

        //先过滤关键字
        List<SysCategory> categories = categoryList.stream().filter( sysCategory -> {
            return StringUtils.hasText(categoryName) ? sysCategory.getCategoryName().contains(categoryName) : true;
        }).collect(Collectors.toList());

        //再从过滤后的数据中,过滤分页数据
        List<SysCategory> list = categories.stream().skip((pageNum - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
        //将数据保存到pageInfo中
        PageInfo<SysCategory> pageInfo = new PageInfo<>(list);
        pageInfo.setTotal(categories.size());
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        return pageInfo;
    }

    @Override
    public SysCategory findById(Long id) {
        //校验id
        Assert.isTrue(id>0,()->{
            throw new QueryDataException("id不能小于0", ErrorCode.DATA_NULL);
        } );
        //从缓存中取
        SysCategory category = categoryCache.get(id);
        return category;
    }

    @Override
    public int updateCategory(SysCategory sysCategory) {
        //判空
        Assert.isTrue(!sysCategory.isEmpty(CheckType.EDIT),()->{
            throw new UpdateDataException("数据为空",ErrorCode.DATA_NULL);
        } );
        //判断是否登录
        SysUserInfo loginUser = LoginUserInfoUtil.getLoginUser();
        Assert.notNull(loginUser,()->{
            throw new UpdateDataException("未登录",ErrorCode.NOT_LOGIN );
        } );

        //设置其他数据
        sysCategory.setUpdateBy(loginUser.getUsername());
        sysCategory.setUpdateTime(new Date());

        //操作数据库
        int count=sysCategoryMapper.updateCategory(sysCategory);

        //发布事件
        applicationContext.publishEvent(new CategoryCacheChangeEvent());

        return count;
    }

    @Override
    public int deleteByIds(List<Long> ids) {
        //判空
        Assert.isTrue(!(ids==null&&ids.isEmpty()),()->{
            throw new UpdateDataException("数据为空",ErrorCode.DATA_NULL);
        } );
        //判断是否登录
        SysUserInfo loginUser = LoginUserInfoUtil.getLoginUser();
        Assert.notNull(loginUser,()->{
            throw new UpdateDataException("未登录",ErrorCode.NOT_LOGIN );
        } );
        //操作数据库
        int count=sysCategoryMapper.deleteByIds(ids);

        //发布事件
        applicationContext.publishEvent(new CategoryCacheChangeEvent());
        return count;
    }
}
